package com.br.aiops.listeners.ladder;

import com.br.aiops.cycle.Cycle;
import com.google.common.collect.Lists;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.time.FastDateFormat;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.text.ParseException;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Objects;

public class LadderCycleList {

    private static final Logger LOGGER = LoggerFactory.getLogger(LadderCycleList.class);

    private List<Cycle> cycles = Lists.newArrayListWithExpectedSize(8);

    /**
     * fastjson反序列化用该构造函数
     */
    public LadderCycleList() {}

    public LadderCycleList(List<Cycle> cycles) {
        this.cycles = cycles;
    }

    /**
     * 根据起始时间、调度周期、和周期阶梯的值(乘以倍数后)计算出周期列表
     * @param firstDate 起始时间
     * @param configDuration 调度周期
     * @param durationValueSteps 周期阶梯的值(乘以倍数后)
     */
    public LadderCycleList(Date firstDate, int configDuration, List<Integer> durationValueSteps) {
        if (CollectionUtils.isEmpty(durationValueSteps)) {
            return;
        }

        Cycle first = new Cycle();
        first.setStart(getCurrentCycleStart(firstDate, configDuration));
        first.setEnd(next(first.getStart(), configDuration));
        first.setDuration(configDuration);
        cycles.add(first);

        for (int i = 1; i <= durationValueSteps.size(); i ++) {
            Integer currentDurationValue = durationValueSteps.get(i - 1);
            Cycle cycle = new Cycle();
            cycle.setStart(cycles.get(i - 1).getEnd());
            cycle.setEnd(next(cycle.getStart(), currentDurationValue));
            cycle.setDuration(currentDurationValue);
            cycles.add(cycle);
        }
    }

    /**
     * 根据日期获取当前周期
     * @param date 日期
     * @return 周期
     */
    public Cycle getCycle(Date date) {
        long minute = Long.parseLong(FastDateFormat.getInstance("yyyyMMddHHmm").format(date));

        for (Cycle cycle : cycles) {
            if (minute >= cycle.getStart() && minute < cycle.getEnd()) {
                return cycle;
            }
        }

        int lastStep = getLastStep();
        long nextStart = -1L;
        long nextEnd = -1L;

        while (true) {
            if (nextStart == -1L) {
                nextStart = cycles.get(cycles.size() - 1).getEnd();
            } else {
                nextStart = nextEnd;
            }
            nextEnd = next(nextStart, lastStep);

            if (minute >= nextStart && minute < nextEnd) {
                return Cycle.builder().start(nextStart).end(nextEnd).duration(lastStep).build();
            }
        }
    }

    public List<Cycle> getCycles() {
        return cycles;
    }

    /**
     * 获取当前duration内的周期刻度（起始时间）
     * @param date 当前时间
     * @return 对应当前周期的开始时间
     */
    private long getCurrentCycleStart(Date date, int duration) {
        return Long.parseLong(FastDateFormat.getInstance("yyyyMMddHHmm").format(date)) / duration * duration;
    }

    private int getLastStep() {
        return (int) (cycles.get(cycles.size() - 1).getEnd() - cycles.get(cycles.size() - 1).getStart());
    }

    private Long next(Long start, int minutes) {
        Date date = null;
        try {
            date = FastDateFormat.getInstance("yyyyMMddHHmm").parse(start.toString());
        } catch (ParseException e) {
            LOGGER.error("解析错误。", e);
        }
        Objects.requireNonNull(date);
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(Calendar.MINUTE, minutes);
        return Long.valueOf(FastDateFormat.getInstance("yyyyMMddHHmm").format(calendar.getTime()));
    }
}
